/**
 * 
 */
package com.cosc716.simulator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.lang.Math;

import com.cosc716.restaurant.domain.Customer;
import com.cosc716.restaurant.domain.CustomerGroup;
import com.cosc716.restaurant.domain.Menu;
import com.cosc716.restaurant.domain.MenuItem;
import com.cosc716.restaurant.domain.Order;
import com.cosc716.restaurant.domain.OrderItem;
import com.cosc716.restaurant.domain.Table;
import com.cosc716.restaurant.domain.collections.OrderQueue;
import com.cosc716.restaurant.domain.collections.WaitingQueue;
import com.cosc716.restaurant.domain.collections.WaitingQueueIterator;
import com.cosc716.restaurant.system.SystemInterface;

/**
 * @author davidmessing
 *
 */
public class DataSourceFIFO implements DataSource {
	
	private int patronEatTime = 5;
	private int preparationCapacity = 50;
	private int orderNumber = 0;
	
	private Random randomGen = new Random();

	/**
	 * 
	 */
	public DataSourceFIFO() {
		// TODO Auto-generated constructor stub
	}

	// Step 1
	@Override
	public void queuePatronsForTime(int timeInterval) {
		
		// generate a random number of groups to arrive
		int numGroups = randomGen.nextInt(2);
		
		for (int i = 0; i < numGroups; i++) {
			// create a customer group to represent a group of patrons arriving
			CustomerGroup group = new CustomerGroup();
			group.setArrivalTime(timeInterval);
			
			// generate customers and add them to the group
			int numCustomers = randomGen.nextInt(8) + 1; // group must have at least 1 person
			for (int j = 0; j < numCustomers; j++) {
				Customer customer = new Customer(patronEatTime);
				group.addCustomer(customer);
			}
			
			// add group to the system waiting queue
			SystemInterface system = SystemInterface.getInstance();
			system.addCustomerGroupToWaitingQueue(group);
			
			// Print update to console
			System.out.println("TIME: " + timeInterval + " | STEP 1 | Group Arrived: " + group);
		}
		
		// Print update to console
		int size = SystemInterface.getInstance().getWaitingQueue().getCustomers().size();
		System.out.println("TIME: " + timeInterval + " | STEP 1 | WaitingQueue.size() = " + size);
	}

	// Step 2
	@Override
	public void seatPatronsForTime(int timeInterval) {
		
		SystemInterface system = SystemInterface.getInstance();
		
		// get available tables
		ArrayList<Table> tables = system.getAvailableTables();
		WaitingQueue queue = system.getWaitingQueue();
		WaitingQueueIterator queueIterator = queue.getQueueIterator();
		
		int size = tables.size();
		if (size > 0) {
			for (int i = 0; i < size; i++) {
				
				// don't continue of there are no groups in the waiting queue 
				if (queueIterator.hasNext() == false) {
					break;
				}
				
				// get next group in waiting queue
				CustomerGroup group = queueIterator.next();
				
				// check tables to see if group can fit
				boolean tableFlag = false;
				for (Table t : tables) {
					if (tableFlag == false) {
						if(t.getTotalSeats() >= group.getSize()) {
							// seat group
							system.addCustomersToTable(group, t);
							// remove group from waiting queue
							system.removeCustomerGroupFromWaitingQueue(group);
							
							// Print update to console
							System.out.println("TIME: " + timeInterval + " | STEP 2 | Group Seated: " + group);
							
							// mark 
							size--;
							tables = system.getAvailableTables();
							tableFlag = true; // exit search
						}
					}
				}
				
			}
		}
		
		// Print update to console
		size = SystemInterface.getInstance().getWaitingQueue().getCustomers().size();
		System.out.println("TIME: " + timeInterval + " | STEP 2 | WaitingQueue.size() = " + size);
	}

	// Step 3
	@Override
	public void placeOrdersForTime(int timeInterval) {
		SystemInterface system = SystemInterface.getInstance();

		// get unordered Tables
		ArrayList<Table> unorderedTables = system.getUnorderedTables(); 

		for(Table unorderedTable : unorderedTables) {
			ArrayList<Customer> tableCustomers = unorderedTable.getSeatedCustomers();
			for(Customer seatedCustomer : tableCustomers) {
				// generate OrderItem
				Order order = generateRandomOrder(seatedCustomer);
				
				// add OrderItem to OrdersQueue
				system.addOrder(order);
				
				// Print update to console
				System.out.println("TIME: " + timeInterval + " | STEP 3 | Order Placed: " + order.getOrderNo());
			}

			// mark Table as ordered
			unorderedTable.setOrderPlaced(true);
		}
		
		// Print update to console
		int size = SystemInterface.getInstance().getOrders().getOrders().size();
		System.out.println("TIME: " + timeInterval + " | STEP 3 | OrderQueue.size() = " + size);
	}

	// Step 4
	@Override
	public void deliverOrdersForTime(int timeInterval) {
		
		SystemInterface system = SystemInterface.getInstance();
		ArrayList<Order> orders = system.getOrders().getOrders();
		//System.out.println("check deliver order time: "+ timeInterval + " " + orders.size());
		int capacity = this.preparationCapacity;
		while (capacity > 0 && orders.size() > 0) {
			Order o = orders.get(0);
			if(o != null) {
				int prepTime = o.getPrepTime();
				
				// spend prepCapacity on OrderItems in OrderQueue
				if (capacity >= prepTime) {
					capacity -= prepTime;
					o.setPrepTime(0);
				}
				else {
					prepTime -= capacity;
					o.setPrepTime(prepTime);
					capacity = 0;
				}

				// if OrderItem.prepStatus == orderItem.prepTime, dequeue OrderItem
				if (o.getPrepTime() == 0) {
					// Print update to console
					System.out.println("TIME: " + timeInterval + " | STEP 4 | Order Delivered: " + o.getOrderNo());
					
					orders.remove(o);
				}
			}
		}
		
//=======
//		// TODO Auto-generated method stub
//		SystemInterface system = SystemInterface.getInstance();
//
//		// get OrdersQueue
//		OrderQueue queue=system.getOrders();
//		ArrayList<Order> orders=queue.getOrders();
//		for(Order order:orders)
//		{
//			ArrayList<OrderItem>order1=order.getItems();
//	
//			for(OrderItem item:order1)
//			{
//				
//				while(item.getPreptime()!=0)
//				{
//					item.prepare();
//				}
//				
//			}
//			System.out.println(order.getOrderNo()+" has delivered");	
//		}
//	
//	
//		// while (prepCapacity > 0)
//		//	spend prepCapacity on OrderItems in OrderQueue
//		// if OrderItem.prepStatus == orderItem.prepTime, dequeue OrderItem
//>>>>>>> .r92
		// Print update to console
		int size = SystemInterface.getInstance().getOrders().getOrders().size();
		System.out.println("TIME: " + timeInterval + " | STEP 4 | OrderQueue.size() = " + size);
	}

	// Step 5
	@Override
	public void removePatronsForTime(int timeInterval) {
		SystemInterface system = SystemInterface.getInstance();
		
		// Get all the tables that customer's are seated at tables
		ArrayList<Table> seatedTables = system.getOrderedTables();
		
		for(Table orderedTable : seatedTables) {
			ArrayList<Customer> tableCustomers = orderedTable.getSeatedCustomers();
			boolean tableDoneMeals = true;
			for(Customer seatedCustomer : tableCustomers) {
				if(seatedCustomer.getEatStatus() > 0) {
					// The customer isn't done eating so mark
					// that the table isn't done their meals.
					tableDoneMeals = false;
					
					// Have the customer eat for this iteration.
					seatedCustomer.eat();
				}
			}
			
			if(tableDoneMeals) {
				for(Customer seatedCustomer : tableCustomers) {
					seatedCustomer.setDepartureTime(timeInterval);
				}
				orderedTable.clearTable();
				
				// Print update to console
				System.out.println("TIME: " + timeInterval + " | STEP 5 | Table cleared: " + orderedTable);
			}
		}
	}
	
	@Override
	public void setPatronEatTime(int timeInterval) {
		this.patronEatTime = timeInterval;
	}
	
	public void setPreparationCapacity(int capacity) {
		this.preparationCapacity = capacity;
	}

	@Override
	public String toString() {
		return "DataSourceFoo []";
	}
	
	private Order generateRandomOrder(Customer customer) {
		// Get the menu
		Menu menu = SystemInterface.getInstance().getMenu();
		
		Order randomOrder = new Order(++orderNumber, customer);
		
		int numberOfItems = randomGen.nextInt(3) + 1; // 3 Items max
		
		for(int i = 0; i < numberOfItems; i++) {
			Iterator menuIterator = menu.getMenuIterator();
			int menuItemNumber = randomGen.nextInt(menu.getMenuItems().size());
			
			for(int j = 0; j < menuItemNumber-1; j++) {
				menuIterator.next();
			}
			MenuItem randomItem = (MenuItem)menuIterator.next();
			
			randomOrder.addMenuItem(randomItem);
			
			}
		
		return randomOrder;
	}
}
